#ifndef OATMEAL_H_983E43B2_0E6D_497E_8317_5C94F649A2A3_
#define OATMEAL_H_983E43B2_0E6D_497E_8317_5C94F649A2A3_

#ifdef __cplusplus
	extern "C" {
#endif

/*/
/ / ------------------------------------------------------------------------------------------------
/ / OATMEAL ENGINE LICENSE AGREEMENT
/ /
/ / Copyright (c) 2007-2010, Jeremy Falcon
/ / oatmealengine.com - All rights reserved.
/ /
/ / The Oatmeal engine is licensed under the LGPL. Plainly speaking this means that you may copy,
/ / distribute, and transmit, use for commercial and non-commercial purposes provided that you do
/ / not alter or misrepresent the origin of the code. Any changes to the library must also be made
/ / available to the public. And, it would be a nice gesture to give credit where it is due.
/ / ------------------------------------------------------------------------------------------------
/*/

////////////////////////////////////////////////////////////////////////////////////////////////////
//// DO NOT MODIFY THIS FILE FOR NROMAL, EVERYDAY USE. IT MAY CAUSE UNEXPECTED ERRORS TO OCCUR. ////
////////////////////////////////////////////////////////////////////////////////////////////////////

// determine if we can take advantage of C99 features
#ifndef __cplusplus
	#ifndef __STDC_VERSION__
		#define C99 0
	#else
		#if __STDC_VERSION__ >= 19990601L
			#define C99 1
		#else
			#define C99 0
		#endif
	#endif
#else
	#define C99 0
#endif

// create a boolean type if this is not being compiled as C++
#if !defined(__cplusplus) && (C99 == 0)
	// mimic a boolean type in C89/C90
	typedef enum {false=0, true=1} bool;
#elif !defined(__cplusplus) && (C99 == 1)
	// use C99's boolean type
	#include <stdbool.h>
#endif

// _WIN32 will also be defined when compiling for 64-bit Windows
#ifdef _WIN32
	#define STRICT					// enable strict type-checking of Windows handles
	#define WIN32_LEAN_AND_MEAN		// allow the exclusion of uncommon features
	#define NOSERVICE				// allow the exclusion of uncommon features
	#define NOMCX					// allow the exclusion of uncommon features
	#define NOIME					// allow the exclusion of uncommon features
	#define NOSOUND					// allow the exclusion of uncommon features
	#define NOCOMM					// allow the exclusion of uncommon features
	#define NOKANJI					// allow the exclusion of uncommon features
	#define NORPC					// allow the exclusion of uncommon features
	#define NOPROXYSTUB				// allow the exclusion of uncommon features
	#define NOIMAGE					// allow the exclusion of uncommon features
	#define NOTAPE					// allow the exclusion of uncommon features

	#include <windows.h>			// fundamental Windows header file
	#include <tchar.h>				// generic text character mapping

	typedef LPTSTR string;
	typedef HWND window;

	typedef __int8 int8;
	typedef __int16 int16;
	typedef __int32 int32;
	typedef __int64 int64;

	typedef unsigned __int8 byte;
	typedef unsigned __int8 uint8;
	typedef unsigned __int16 uint16;
	typedef unsigned __int32 uint32;
	typedef unsigned __int64 uint64;
#else
	// X11 includes
	#ifdef X11
		#include <unistd.h>
		#include <X11/X.h>
		#include <X11/Xlib.h>
		#include <X11/Xatom.h>
		#include <X11/Xutil.h>
		#include <X11/keysym.h>
	#endif

	// mimic the Windows naming conventions for text mapping types
	// helps make code much more readable when we care about different code types
	#ifdef UNICODE
		#define _T(x) L ## x

		#ifndef _MAC
			typedef wchar_t* string;
		#else
			typedef unsigned short* string;
		#endif
	#else
		#define _T(x) x
		typedef char* string;
	#endif

	typedef char int8;
	typedef short int16;
	typedef int int32;
	typedef long long int64;

	typedef unsigned char byte;
	typedef unsigned char uint8;
	typedef unsigned short uint16;
	typedef unsigned int uint32;
	typedef unsigned long long uint64;

	typedef uint32 window;
#endif

// portable type definitions
typedef float float32;
typedef long double float64;

// custom structs
typedef struct tagRect
{
	int32 nLeft;
	int32 nTop;
	int32 nRight;
	int32 nBottom;

} rect;

typedef struct tagSize
{
	int32 nWidth;
	int32 nHeight;

} size;

typedef struct tagPoint
{
	int32 nX;
	int32 nY;

} point;

typedef struct tagColor
{
	float32 fRed;
	float32 fGreen;
	float32 fBlue;
	float32 fAlpha;

} color;

// identify various popular 32-bit and 64-bit operating systems
typedef enum tagOS
{
	Unknown			=  -1,	// unknown
	WinUnknown		=   0,	// unknown Windows
	MacUnknown		=   1,	// unknown Macintosh
	Win32s			= 100,	// represents Win32s subsystem for Win 3.x
	Win95			= 101,	// represents 9x version 4.0
	Win95OSR2		= 102,	// represents 9x version 4.0 B and C
	Win98			= 103,	// represents 9x version 4.1
	Win98SE			= 104,	// represents 9x version 4.1 SE
	WinME			= 105,	// represents 9x version 4.9
	WinNT35			= 106,	// represents NT-based version 3.5
	WinNT4			= 107,	// represents NT-based version 4.0
	Win2000			= 108,	// represents NT-based version 5.0
	WinXP			= 109,	// represents NT-based version 5.1
	WinServer2003	= 110,	// represents NT-based version 5.2
	WinVista		= 111,	// represents NT-based version 6.0
	WinServer2008	= 112,	// represents NT-based version 6.0
	Win7			= 113,	// represents NT-based version 7.0
	WinGreater		= 114	// represents NT-based version greater than 7.0

	//		MacOS8,
	//		MacOS9,
	//		MacOSX

} OS;

typedef struct tagOSINFO
{
	OS osFamily;
	float32 fVersion;
	uint8 nServicePack;
	bool b64Bit;

} OSINFO;

// general macros
#define OATEVENT __fastcall

// safely determine the length of a string array
#ifdef UNICODE
	#define LEN(szBuffer) (sizeof(szBuffer) / sizeof(string))
#else
	#define LEN(szBuffer) sizeof(szBuffer)
#endif

// callback event handlers / function pointers
typedef bool (OATEVENT * OATONCLOSEPROC) (void);

// numerical constants
#define PI					3.1415926535897931
#define TWO_PI				6.2831853071795862
#define	SQRT2				1.4142135623730951
#define	SQRT1_2				0.7071067811865476

// convenience macros
#define DIVIDE_POT(n, p)		(n >> p)
#define MULTIPLY_POT(n, p)		(n << p)
#define MIN(x, y)				(((x) < (y)) ? (x) : (y))
#define MAX(x, y)				(((x) > (y)) ? (x) : (y))
#define DEGREES_TO_RADIANS(x)	((x) * 0.017453292)
#define RADIANS_TO_DEGREES(x)	((x) * 57.29577951)

// _WIN32 will also be defined when compiling for 64-bit Windows
#ifdef _WIN32
	// to help the readability of API declarations
	#ifdef _WINDLL
		#define OATAPI(ReturnType) __declspec (dllexport) ReturnType __stdcall
	#else
		#define OATAPI(ReturnType) __declspec (dllimport) ReturnType __stdcall
	#endif

	// macros for using string data
	#define MATCH(szOne, szTwo)				(_tcscmp(szOne, szTwo) == 0)
	#define NMATCH(szOne, szTwo, nCount)	(_tcsncmp(szOne, szTwo, nCount) == 0)
	#define IMATCH(szOne, szTwo)			(_tcsicmp(szOne, szTwo) == 0)
	#define NIMATCH(szOne, szTwo, nCount)	(_tcsnicmp(szOne, szTwo, nCount) == 0)
	#define FORMAT(szDest, szFormat, ...)	(_stprintf_s(szDest, LEN(szDest), szFormat, __VA_ARGS__) != -1)
	#define COPY(szDest, szSrc)				(_tcscpy_s(szDest, LEN(szDest), szSrc) == 0)
	#define NCOPY(szDest, szSrc, szCount)	(_tcsncpy_s(szDest, LEN(szDest), szSrc, szCount) == 0)
#else
	// to help the readability of API declarations
	#define OATAPI(ReturnType) ReturnType __stdcall

	// macros for matching string data (both case sensitive and insensitive versions)
	#ifdef UNICODE
		#define MATCH(szOne, szTwo)				(wcscmp(szOne, szTwo) == 0)
		#define NMATCH(szOne, szTwo, nCount)	(wcsncmp(szOne, szTwo, nCount) == 0)
		#define IMATCH(szOne, szTwo)			(wcsicmp(szOne, szTwo) == 0)
		#define NIMATCH(szOne, szTwo, nCount)	(wcsincmp(szOne, szTwo, nCount) == 0)
		#define FORMAT(szDest, szFormat, ...)	(swprintf(szDest, szFormat, __VA_ARGS__) != -1)
		#define COPY(szDest, szSrc)				(wcscpy(szDest, szSrc) == 0)
		#define NCOPY(szDest, szSrc, szCount)	(wcsncpy(szDest, szSrc, szCount) == 0)
	#else
		#define MATCH(szOne, szTwo)				(strcmp(szOne, szTwo) == 0)
		#define NMATCH(szOne, szTwo, nCount)	(strncmp(szOne, szTwo, nCount) == 0)
		#define IMATCH(szOne, szTwo)			(stricmp(szOne, szTwo) == 0)
		#define NIMATCH(szOne, szTwo, nCount)	(strincmp(szOne, szTwo, nCount) == 0)
		#define FORMAT(szDest, szFormat, ...)	(sprintf(szDest, szFormat, __VA_ARGS__) != -1)
		#define COPY(szDest, szSrc, szCount)	(strcpy(szDest, szSrc) == 0)
		#define NCOPY(szDest, szSrc, szCount)	(strncpy(szDest, szSrc, szCount) == 0)
	#endif
#endif

// general API declarations
OATAPI(string)	oatGetAppName				(string szAppName, size_t nBuffSize);
OATAPI(string)	oatGetCompanyName			(string szCompanyName, size_t nBuffSize);
OATAPI(bool)	oatInitEngineFullscreen		(const uint8 nBPP, const uint8 nVertRefresh, const bool bSingleInstance);
OATAPI(bool)	oatInitEngineWindowed		(const bool bSingleInstance);
OATAPI(bool)	oatIsEngineRunning			(void);
OATAPI(void)	oatSetAppName				(const string szAppName);
OATAPI(void)	oatSetCompanyName			(const string szCompanyName);
OATAPI(void)	oatSetEventOnClose			(const OATONCLOSEPROC pCallback);
OATAPI(void)	oatSetSilentErrors			(const bool bSilentErrors);
OATAPI(void)	oatSetProjection			(void);

// windowing API declarations
OATAPI(window)	oatCreateWindow				(const size *pDefault, const color *pBackground, const bool bResizable, const bool bForceSize);
OATAPI(window)	oatDestroyWindow			(const window wndID);
OATAPI(void)	oatLockWindowAspectRatio	(const window wndID, const bool bAspectRatio);
OATAPI(bool)	oatSetWindowIcon			(const window wndID, const uint32 nResourceID);
OATAPI(void)	oatSetWindowTitle			(const window wndID, const string szTitle);
OATAPI(void)	oatShowWindow				(const window wndID, const bool bVisible);

// system API declarations
OATAPI(uint8)	oatGetCPUCount				(void);
OATAPI(uint8)	oatGetCPUCoreCount			(void);
OATAPI(uint64)	oatGetCPUSpeed				(void);
OATAPI(uint64)	oatGetFreeMemoryAmount		(void);
OATAPI(uint64)	oatGetMemoryAmount			(void);
OATAPI(OS)		oatGetOSVersion				(void);
OATAPI(bool)	oatIsMultiMonitorSupported	(void);

#ifdef __cplusplus
	}
#endif

#endif  // OATMEAL_H_